#ifndef XABSTRACTSYNTAXTREE_H
#define XABSTRACTSYNTAXTREE_H
#include <memory>
#include <vector>
#include <xscript/xdefs.h>
#include <xscript/xnameholder.h>
#include <xscript/xitem.h>
#include <xscript/xtoken.h>
#include <xscript/xhierarchy.h>

enum XAbstractSyntaxTreeType {
    XAbstractSyntaxTreeType_Undefined = 0,
    XAbstractSyntaxTreeType_Let,
    XAbstractSyntaxTreeType_Set,
    XAbstractSyntaxTreeType_Print,
    XAbstractSyntaxTreeType_And,
    XAbstractSyntaxTreeType_Or,
    XAbstractSyntaxTreeType_Not,
    XAbstractSyntaxTreeType_Greate,
    XAbstractSyntaxTreeType_GreateOrEqual,
    XAbstractSyntaxTreeType_Less,
    XAbstractSyntaxTreeType_LessOrEqual,
    XAbstractSyntaxTreeType_Equal,
    XAbstractSyntaxTreeType_If,
    XAbstractSyntaxTreeType_IfElse,
    XAbstractSyntaxTreeType_Else,
    XAbstractSyntaxTreeType_For,
    XAbstractSyntaxTreeType_While,
    XAbstractSyntaxTreeType_Break,
    XAbstractSyntaxTreeType_Return,
    XAbstractSyntaxTreeType_Plus,
    XAbstractSyntaxTreeType_Minus,
    XAbstractSyntaxTreeType_Multi,
    XAbstractSyntaxTreeType_Div,
    XAbstractSyntaxTreeType_Variable,
    XAbstractSyntaxTreeType_Value,
    XAbstractSyntaxTreeType_Block,
    XAbstractSyntaxTreeType_Function,
    XAbstractSyntaxTreeType_Max
};

class XAbstractSyntaxTree : public XHierarchy<XAbstractSyntaxTree>, public XNameHolder {
  public:
    static XAbstractSyntaxTreePtr createFromToken(XTokenPtr token);

    XAbstractSyntaxTree() = delete;
    XAbstractSyntaxTree(XTokenPtr inputToken);
    virtual ~XAbstractSyntaxTree() = default;
  public:
    XTokenPtr getToken()const {return token;}
    virtual XAbstractSyntaxTreeType getTreeType()const {return XAbstractSyntaxTreeType_Undefined;}
    virtual bool invoke(std::shared_ptr<XVariableTable> table) = 0;
    std::shared_ptr<XItem> getResult()const {return result;}
    virtual bool shouldInvokeSibling()const {return invokeSibling;}
    virtual bool shouldBreak()const {return invokeBreak;}
    virtual bool shouldReturn()const {return invokeReturn;}
    virtual bool isFilled()const {return false;}
    virtual void accept(std::shared_ptr<XAbstractSyntaxTreeVisitor> visitor);

    bool swtichVariableTable(std::shared_ptr<XVariableTable> table, const std::wstring& module, uint32_t block);
  protected:
    XTokenPtr token;
    std::shared_ptr<XItem> result;
    bool invokeSibling = false;
    bool invokeBreak = false;
    bool invokeReturn = false;
};

#endif // XABSTRACTSYNTAXTREE_H
